<?php
/***
 * Candy框架 框架控制器的基类
 * 
 * $Author: 刘森 (fingerboy@qq.com) $
 * $Date: 2019-08-01 23:38:42 $   
 */

//语法严格模式开启
declare(strict_types=1);
namespace Candy\Core;

defined('CANDY') OR die('You Are A Bad Guy. o_O???');

Class Action extends View {
	/**
	 * 该方法用来运行框架中的操制器
	 */
	public function working(): void
	{
		parent::__construct();
		
		//解析
		if(is_null(C('S404'))){
			//如果有子类Common，调用这个类的init()方法 做权限控制
			if(method_exists($this, 'init')){
				call_user_func([$this, 'init']);		
			}
			
			//根据动作去找对应的方法
			if(method_exists($this, $this->action)){
				//私有方法禁止访问
				if (preg_match('/^[_]/i', $this->action)) {
					showTplMsg('error', $this->action. '操作被禁止访问。');
				}
				
				//前置操作
				$before_action = '_before_'. $this->action .'_';
				if(method_exists($this, $before_action)){
					call_user_func([$this, $before_action]);
				}
				
				//项目权限检查
				$checkAuth = true;
				$appName = C('APPNAME');
				if((!is_null(G('appNode')) && in_array($appName, G('appNode')['auth'])) || (!is_null(C('ISADDON')) && Addon::getAddonAuth($appName))){
					Debug::addMsg('<font color="red">'.$appName . (is_null(C('ISADDON')) ? '项目' : '插件') .'开启操作权限自动检查!</font>', 6);
					$checkAuth = Node::forceAuth();
				}else{
					Node::getActionInfo();
				}
				
				if($checkAuth){
					call_user_func([$this, $this->action]);
				}else{
					$exist = $this->templateExist('Public/noAuth');
					if($exist){
						$this->display('Public/noAuth');
					}else{
						$noauth = L($this->action.'NoAuth') ?: '权限不够!';
						showTplMsg('error', $noauth);
					}
				}
			}else{
				//模版存在
				$exist = $this->templateExist( $this->control .'/'. $this->action );
				if($exist){
					$this->display();
				}else{
					Debug::addMsg('<font color=\'red\'>没有'. $this->action . '这个操作！</font>', 4);
					$this->display404('没有'. $this->action . '这个操作！');
				}
			}	
		}else{
			if(is_dir(C('APP_PATH'))){
				$this->display404($this->control .'控制器不存在。');
			}else{
				$this->display404(C('APPNAME').'项目'. (is_null(G('Addons')) ? '' : '(扩展)') .'不存在。');
			}
		}
	}
	
	/** 
	 * 用于在控制器中进行位置重定向
	 *
	 * @param	string	$path	用于设置重定向的位置
	 * @param	string	$args 	用于重定向到新位置后传递参数
	 * 
	 * $this->redirect("index")  /当前模块/index
	 * $this->redirect("user/index") /user/index
	 * $this->redirect("user/index", 'page/5') /user/index/page/5
	 */
	public function redirect(string $path,string $args = ''): void
	{
		//API模式
		if(!is_null(C('API'))){
			$msg = ['status'=>'ok','msg'=>'操作重定向','operate'=>U($path,$args,C('API'))];
			$this->assign($msg);
			$this->display();
			stop();
		}
		//使用js跳转前面可以有输出
		echo '<script>';
		echo 'location="'. U($path, $args) .'"';
		echo '</script>';
		stop();
	}
	
	/**
	 * 成功的消息提示框
	 *
	 * @param	string	$mess		用示输出提示消息
	 * @param	int	$timeout	设置跳转的时间，单位：秒
	 * @param	string	$location	设置跳转的新位置
	 */
	public function success(string $mess='操作成功',int $timeout=1,string $location='',string $title=''):bool
	{
		$this->apidataClearAll(); //清楚其他变量
		$this->assign('status', 1);  //如果成功 $mark=true
		$this->pub($mess, $timeout, $location, $title);
		$exist = $this->templateExist('Public/success');
		if($exist){
			$this->display('Public/success');
		}
		return false;
	}
	
	/**
	 * 失败的消息提示框
	 *
	 * @param	string	$mess		用示输出提示消息
	 * @param	int	$timeout	设置跳转的时间，单位：秒
	 * @param	string	$location	设置跳转的新位置
	 */
	public function error(string $mess='操作失败',int $timeout=3,string $location='',string $title=''):bool
	{
		$this->apidataClearAll(); //清楚其他变量
		$this->assign('status', 0); //如果失败 $mark=false
		$this->pub($mess, $timeout, $location, $title);
		$exist = $this->templateExist('Public/success');
		if($exist){
			$this->display('Public/success');
		}
		return false;
	}
	
	/**
	 * 跳转函数
	 *
	 * @param	string	$mess		用示输出提示消息
	 * @param	int	$timeout	设置跳转的时间，单位：秒
	 * @param	string	$location	设置跳转的新位置
	 */
	private function pub(string $mess,int $timeout,string $location,string $title): void
	{	
		$this->caching=0;     //设置缓存关闭
		
		//有的消息是多个放在数组中， 合成字符串
		if(is_array($mess))
			$mess = implode(',', $mess);
		
		$this->assign('message', $mess);
		
		//API模式
		if(!is_null(C('API'))){
			if(!is_null(C('APIDATA'))){
				$this->assign('apidata', C('APIDATA'));
			}
				
			$this->display();
			stop();
		}
		
		if($location==''){
			$location= $_SERVER['HTTP_REFERER'];
		}else if(stristr($location, 'http://')){
			$location=urldecode($location);
		}else{
			$location = U($location);
		}
		
		$href = $location;
		
		$this->assign('timeout', $timeout);
		$this->assign('location', $location);
		$this->assign('href', $href);
	}
	
	/**
	 * 获取对象 非静态对象
	 */
	public function instance(string $className):object
	{	
		return Container::getInstance()->get($className);
	}
	
	/**
	 * 404
	 */
	public function display404(string $msg): void
	{
		//debug模式下不输出404
		if(isDebug()){
			$msg = C('S404') === true ? $msg : C('S404');
			$this->halt($msg);
			//设置输出Debug模式的信息
			showDebugMsg();
		}else{
			//定义404并退出
			$exist = $this->templateExist('Public/404');
			if($exist){
				$this->display('Public/404');
			}
		}
	}
}
